package com.cardone.persistent.aspect;

import com.cardone.common.cache.util.CacheUtils;
import com.cardone.context.ContextHolder;
import com.cardone.persistent.support.UpdateAction;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.support.TaskUtils;

import java.util.Collection;
import java.util.Map;

/**
 * Created by Administrator on 2014/11/1.
 */
@lombok.extern.slf4j.Slf4j
public class RedundancyAspect {
    Multimap<String, UpdateAction> updateActionMap;

    /**
     * 批量处理
     *
     * @param joinPoint
     */
    public void batchUpdate(final org.aspectj.lang.JoinPoint joinPoint) {
        this.init();

        if (updateActionMap.size() < 1) {
            return;
        }

        Class<?>[] targetClasss = joinPoint.getTarget().getClass().getInterfaces();

        if (ArrayUtils.isEmpty(targetClasss)) {
            targetClasss = new Class<?>[]{joinPoint.getTarget().getClass()};
        }

        for (Class<?> targetClass : targetClasss) {
            String key = targetClass.getName() + "." + joinPoint.getSignature().getName();

            ContextHolder.getBean(TaskExecutor.class).execute(TaskUtils.decorateTaskWithErrorHandler(() -> {
                updateActionRun(key);

                CacheUtils.clear(targetClass.getName());
            }, null, true));
        }
    }

    public void updateActionRun(String key) {
        if (updateActionMap.size() < 1) {
            return;
        }

        if (!updateActionMap.containsKey(key)) {
            return;
        }

        Collection<UpdateAction> updateActions = this.updateActionMap.get(key);

        if (CollectionUtils.isEmpty(updateActions)) {
            return;
        }

        for (UpdateAction updateAction : updateActions) {
            try {
                updateAction.run();
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
    }

    private void init() {
        if (updateActionMap != null) {
            return;
        }

        updateActionMap = HashMultimap.create();

        Map<String, UpdateAction> updateActionMap = ContextHolder.getApplicationContext().getBeansOfType(UpdateAction.class);

        this.initUpdateActionMap(updateActionMap);
    }

    private void initUpdateActionMap(Map<String, UpdateAction> updateActionMap) {
        if (MapUtils.isEmpty(updateActionMap)) {
            return;
        }

        for (Map.Entry<String, UpdateAction> updateActionEntry : updateActionMap.entrySet()) {
            if (ArrayUtils.isEmpty(updateActionEntry.getValue().getNames())) {
                continue;
            }

            for (String updateActionKey : updateActionEntry.getValue().getNames()) {
                this.updateActionMap.put(updateActionKey, updateActionEntry.getValue());
            }
        }
    }
}

